package com.deer.wms.ASN.manage.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.deer.wms.ASN.manage.constant.AsnManageConstant;
import com.deer.wms.ASN.manage.dao.AcceptRecordMapper;
import com.deer.wms.ASN.manage.dao.AsnDetailMapper;
import com.deer.wms.ASN.manage.dao.AsnMasterMapper;
import com.deer.wms.ASN.manage.dao.QcRecordMapper;
import com.deer.wms.ASN.manage.model.asn.AsnDetail;
import com.deer.wms.ASN.manage.model.asn.AsnDetailCriteria;
import com.deer.wms.ASN.manage.model.asn.AsnDetailDto;
import com.deer.wms.ASN.manage.model.asn.AsnMaster;
import com.deer.wms.ASN.manage.model.buy.RequestBuy;
import com.deer.wms.ASN.manage.model.buy.RequestBuyDetail;
import com.deer.wms.ASN.manage.model.buy.RequestBuyDetailCriteria;
import com.deer.wms.ASN.manage.model.buy.RequestBuyDetailDto;
import com.deer.wms.ASN.manage.model.in.AcceptInsert;
import com.deer.wms.ASN.manage.model.in.AcceptRecord;
import com.deer.wms.ASN.manage.model.in.AcceptRecordCriteria;
import com.deer.wms.ASN.manage.model.qc.QcRecord;
import com.deer.wms.ASN.manage.model.qc.QcRecordCriteria;
import com.deer.wms.ASN.manage.model.qc.QcRecordDto;
import com.deer.wms.ASN.manage.service.*;
import com.deer.wms.base.system.dao.ErpBackRecordMapper;
import com.deer.wms.base.system.model.*;
import com.deer.wms.base.system.model.Cell.CellInfo;
import com.deer.wms.base.system.model.Item.ItemInfo;
import com.deer.wms.base.system.model.Supplier.SupplierInfo;
import com.deer.wms.base.system.service.CellInfoService;
import com.deer.wms.base.system.service.ItemInfoService;
import com.deer.wms.base.system.service.PackDetailService;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.model.Inventory.InventoryTransact;
import com.deer.wms.inventory.model.Inventory.ItemBatch;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.inventory.service.ItemBatchService;
import com.deer.wms.inventory.service.SerialNoService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.service.SuperServiceImpl;
import com.deer.wms.project.root.util.BeanUtils;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.project.root.util.HttpClient;
import com.deer.wms.project.root.util.StringUtils;
import com.deer.wms.review.manage.service.BillRecordService;
import com.deer.wms.system.manage.constant.SystemManageConstant;
import com.deer.wms.system.manage.model.organization.Organization;
import com.deer.wms.system.manage.model.ware.WareInfo;
import com.deer.wms.system.manage.service.CodeRuleService;
import com.deer.wms.system.manage.service.OrganizationService;
import com.deer.wms.system.manage.service.ValidatorService;
import com.deer.wms.system.manage.service.WareInfoService;
import com.deer.wms.ware.task.model.SO.SoDetail;
import com.deer.wms.ware.task.model.SO.SoMaster;
import com.deer.wms.ware.task.service.SoDetailService;
import com.deer.wms.ware.task.service.SoMasterService;
import com.google.common.base.Preconditions;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 *
 * @author 郭靖勋
 * @since 2019/12/18
 */
@Service
@Transactional //事务回滚
public class AcceptRecordServiceImpl extends SuperServiceImpl<AcceptRecordMapper, AcceptRecord> implements AcceptRecordService {
    @Autowired
    private AcceptRecordMapper acceptRecordMapper;

    @Autowired
    private ItemBatchService itemBatchService;

    @Autowired
    private InventoryTransactService inventoryTransactService;

    @Autowired
    private AcceptRecordService acceptRecordService;

    @Autowired
    private AsnMasterService asnMasterService;

    @Autowired
    private AsnDetailService asnDetailService;

    @Autowired
    private RequestBuyService requestBuyService;

    @Autowired
    private RequestBuyDetailService requestBuyDetailService;

    @Autowired
    private SerialNoService serialNoService;

    @Autowired
    private BillRecordService billRecordService;

    @Autowired
    private ValidatorService validatorService;

    @Autowired
    private CellInfoService cellInfoService;

    @Autowired
    private AcceptExService acceptExService;

    @Autowired
    private QcMasterService qcMasterService;

    @Autowired
    private ItemInfoService itemInfoService;

    @Autowired
    private OrganizationService organizationService;

    @Autowired
    private WareInfoService wareInfoService;

    @Autowired
    private CodeRuleService codeRuleService;

    @Autowired
    private PackDetailService packDetailService;

    @Autowired
    private AsnMasterMapper asnMasterMapper;

    @Autowired
    private AsnDetailMapper asnDetailMapper;

    @Autowired
    private QcRecordMapper qcRecordMapper;

    @Autowired
    private ErpBackRecordMapper erpBackRecordMapper;

    @Autowired
    private SoMasterService soMasterService;

    @Autowired
    private SoDetailService soDetailService;

    public String getNextBoxCode() {
        return validatorService.getNextId("box_info").toString();
    }

    @Override
    public List<AcceptRecord> findList(AcceptRecordCriteria criteria) {
        return acceptRecordMapper.findList(criteria);
    }

    @Override
    public Integer accept(AcceptInsert acceptInsert) {
        //Step0.准备数据
        //使用批次策略生成
//        ItemBatch itemBatch = acceptInsert;
//        itemBatch.setOrderType(2);
//        itemBatch = itemBatchService.createItemBatch(itemBatch);

        //获取固定格式批次码 [yyyyMMdd流水号] 批次可能存在 也可能不存在
        Map<String, Object> map = new HashMap<>();
        map.put("detail_no", acceptInsert.getAsnBillNo());
        map.put("in_date", DateUtil.today());
        ItemBatch itemBatch = itemBatchService.getOneByMap(map);
        if (ObjectUtil.isNull(itemBatch)) {
            itemBatch = itemBatchService.createSimpleItemBatch(acceptInsert.getAsnBillNo());
        }
        acceptInsert.setBatchId(itemBatch.getBatchId());
        acceptInsert.setBatchName(itemBatch.getBatchName());

        //Step1.创建收货单并确认
        List<AcceptRecord> list = this.saveAndConfirmAcceptRecord(ListUtil.toList(acceptInsert));

        return list.get(0).getId();
    }

    /**
     * 校验收货数据是否合法，合法后才允许后续的操作
     * @param acceptInsert acceptInsert
     */
    private void validateAndPrepareAcceptData(AcceptInsert acceptInsert) {
        //仓库
        WareInfo wareInfo = wareInfoService.getById(acceptInsert.getWareId());
        Preconditions.checkNotNull(wareInfo, "根据仓库id[%s]获取仓库失败!", new Object[]{acceptInsert.getWareId()});
        acceptInsert.setWareName(wareInfo.getWareName());
//        //货主
//        Organization organization = organizationService.getById(acceptInsert.getOrganizationId());
//        Preconditions.checkNotNull(organization, "根据货主id[%s]获取货主失败!", new Object[]{acceptInsert.getOrganizationId()});
//        acceptInsert.setOrganizationName(organization.getOrganizationName());
//        //库位
//        CellInfo cellInfo = cellInfoService.findByCodeAndWareId(acceptInsert.getToCellCode(), acceptInsert.getWareId());
//        Preconditions.checkNotNull(cellInfo, "根据仓库id[%s],库位[%s]获取收货库位失败!", new Object[]{acceptInsert.getWareId(), acceptInsert.getToCellCode()});
        //物料
        ItemInfo itemInfo = itemInfoService.getOneByField("item_code", acceptInsert.getItemCode());
        Preconditions.checkNotNull(itemInfo, "根据物料编码[%s]获取物料失败!", new Object[]{acceptInsert.getItemCode()});
        acceptInsert.setItemName(itemInfo.getItemName());
        //TODO:容器
    }

    /**
     * 收货单确认后更新
     * @param acceptRecord
     */
    private void updateASNState(AcceptRecord acceptRecord) {
        AsnDetail asnDetail = asnDetailService.getOneByField("detail_no", acceptRecord.getAsnDetailNo());
        //更新ASN明细
        asnDetail.setAcceptQuantity(acceptRecord.getQuantity() + asnDetail.getAcceptQuantity());
        asnDetail.setAcceptTime(acceptRecord.getAcceptTime());
        if (asnDetail.getAcceptQuantity().equals(asnDetail.getExpectQuantity())) {
            asnDetail.setState(AsnManageConstant.ASN_STATE_ALL);
        } else {
            asnDetail.setState(AsnManageConstant.ASN_STATE_PARTED);
        }
        if (acceptRecord.getQuantity() > asnDetail.getExpectQuantity()) {
            asnDetail.setState(AsnManageConstant.ASN_STATE_OVER);
        }
//        asnDetail.setExState(0);???
        asnDetailService.updateById(asnDetail);

        //更新ASN状态，若明细全部验收则入库单收获完毕
        AsnDetailCriteria criteria = new AsnDetailCriteria();
        criteria.setBillNo(asnDetail.getBillNo());
        List<AsnDetailDto> asnDetails = asnDetailService.findList(criteria);
        Boolean asnAccept = true;
        AsnMaster asnMaster = asnMasterService.findBy("bill_no", asnDetail.getBillNo());
        for (AsnDetail ad : asnDetails) {
            if (ObjectUtil.notEqual(AsnManageConstant.ASN_STATE_ALL, ad.getState())) {
                asnAccept = false;
                break;
            }
        }
        if (asnAccept) {
            asnMaster.setAsnState(AsnManageConstant.ASN_STATE_ALL);
        } else {
            asnMaster.setAsnState(AsnManageConstant.ASN_STATE_PARTED);
        }
        asnMasterService.updateById(asnMaster);

        //TODO:更新采购单信息
//        updatePOState(acceptInsert, asnDetail, acceptRecord);
    }

    /**
     * 更新采购单状态
     *
     * @param acceptInsert AcceptInsert
     * @param asnDetail    入库单明细
     * @param acceptRecord 收货记录
     */
    private void updatePOState(AcceptInsert acceptInsert, AsnDetail asnDetail, AcceptRecord acceptRecord) {
        if (acceptInsert.getRequestDetailDetailNo() != null) {
            RequestBuyDetail requestBuyDetail = requestBuyDetailService.findByDetailNo(asnDetail.getRequestDetailDetailNo());
            requestBuyDetail.setAcceptQuantity(acceptRecord.getQuantity() + requestBuyDetail.getAcceptQuantity());
            requestBuyDetail.setAcceptTime(acceptInsert.getAcceptTime());
            if (acceptRecord.getQuantity().equals(requestBuyDetail.getExpectQuantity())) {
                requestBuyDetail.setState(AsnManageConstant.ASN_STATE_ALL);
            } else {
                requestBuyDetail.setState(AsnManageConstant.ASN_STATE_PARTED);
            }
            if (acceptRecord.getQuantity() > (requestBuyDetail.getExpectQuantity())) {
                requestBuyDetail.setState(AsnManageConstant.ASN_STATE_OVER);
            }
            requestBuyDetailService.updateById(requestBuyDetail);

            //根据detail的收货状态判断 master的采购收货状态
            RequestBuyDetailCriteria criteria1 = new RequestBuyDetailCriteria();
            criteria1.setBillNo(requestBuyDetail.getBillNo());
            List<RequestBuyDetailDto> requestBuyDetails = requestBuyDetailService.findList(criteria1);

            Boolean requestAccept = true;
            RequestBuy requestBuy = requestBuyService.findBy("bill_no", requestBuyDetail.getBillNo());
            for (RequestBuyDetail requestBuyDetail1 : requestBuyDetails) {
                if (requestBuyDetail1.getState() != 3) {
                    requestAccept = false;
                }
                if (acceptRecord.getQuantity() > (requestBuyDetail1.getExpectQuantity())) {
                    requestBuyDetail.setState(AsnManageConstant.ASN_STATE_OVER);
                }
                if (acceptRecord.getQuantity() < (requestBuyDetail1.getExpectQuantity())) {
                    requestBuy.setAcceptState(AsnManageConstant.ASN_STATE_PARTED);
                }
                requestBuyService.updateById(requestBuy);
            }
            if (requestAccept) {
                requestBuy.setAcceptState(AsnManageConstant.ASN_STATE_ALL);
                requestBuyService.updateById(requestBuy);
            }
        }
    }

    /**
     * 获取物料对应的质检策略
     *
     * @param itemCode 物料编码
     * @return String
     */
    private String getQcTacticCode(String itemCode) {
//        Integer organizationId = acceptInsert.getOrganizationId();
        ItemInfo itemInfo = itemInfoService.findBy("item_code", itemCode);
        String qcTacticCode = itemInfo.getQcTacticCode();
//        if (StringUtils.isNotEmpty(itemInfo.getQcTacticCode())) {
//            qcTacticCode = itemInfo.getQcTacticCode();
//        } else {
//            Organization organization = organizationService.getById(organizationId);
//            if (organization != null && StringUtils.isNotEmpty(organization.getQcTacticCode())) {
//                qcTacticCode = organization.getQcTacticCode();
//            }
//        }
        return qcTacticCode;
    }

    @Override
    public List<AcceptRecord> findDayList(AcceptRecordCriteria criteria) {
        return acceptRecordMapper.findDayList(criteria);
    }

    @Override
    public List<AcceptRecord> findCanTongbu() {
        return acceptRecordMapper.findCanTongbu();
    }

    @Override
    public List<AcceptRecord> saveAndConfirmAcceptRecord(List<AcceptInsert> acceptInserts) {
        List<AcceptRecord> acceptRecords = this.createAcceptRecord(acceptInserts);
        return this.confirmAcceptRecord(acceptRecords);
    }

    @Override
    public List<AcceptRecord> createAcceptRecord(List<AcceptInsert> acceptInserts) {
        List<AcceptRecord> list = new ArrayList<>();
        for (AcceptInsert acceptInsert : acceptInserts) {
            //Step1.各类数据数据校验，不合法给与异常信息提示
            //仓库  货主 库位 容器  物料
            this.validateAndPrepareAcceptData(acceptInsert);

            //Step2.组装收货单数据
            AcceptRecord acceptRecord = new AcceptRecord();
            BeanUtils.copyProperties(acceptInsert, acceptRecord);
            //收货单号
            acceptRecord.setAcceptRecordCode(codeRuleService.generateCode(SystemManageConstant.CODE_RULE_AC));
            //收货库位
            acceptRecord.setCellCode(acceptInsert.getToCellCode());
            //收货容器
            acceptRecord.setBoxCode(acceptInsert.getToBoxCode());
            //收货数量
            acceptRecord.setQuantity(acceptInsert.getToQuantity());
            //包装及转换率
            acceptRecord.setPackDetailId(acceptInsert.getToPackDetailId());
            acceptRecord.setPackDescribe(acceptInsert.getToPackDescribe());
            acceptRecord.setTransRatio(acceptInsert.getToTransRatio());
            //单据类型? 是否需要

            //收货单状态-默认0 新建
            acceptRecord.setState(AsnManageConstant.ACCEPT_STATE_INIT);
            //质检状态 0免检 1待检 2已检
            if (StringUtils.isNotEmpty(getQcTacticCode(acceptRecord.getItemCode()))) {
                //存在质检策略说明需要质检
                //FIXME: 暂时只区分需不需要质检。后期需要做到根据质检策略来具体处理
                acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_TODO);
            }else {
                acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_EXEMPTION);
            }
            //收货日期
            acceptRecord.setAcceptTime(DateUtil.now());

            //Step3.保存
            acceptRecordService.save(acceptRecord);
            list.add(acceptRecord);
        }
        return list;
    }

    @Override
    public List<AcceptRecord> confirmAcceptRecord(List<AcceptRecord> acceptRecords) {
        for (AcceptRecord acceptRecord : acceptRecords) {
            //Step1.判断收货单是否满足确认的条件 修改状态
            if(ObjectUtil.notEqual(AsnManageConstant.ACCEPT_STATE_INIT, acceptRecord.getState())){
                throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "收货单不为新建状态，不可确认!");
            }
            acceptRecord.setState(AsnManageConstant.ACCEPT_STATE_CONFIRMED);

            //Step2.生成库存事务请求 并提交
            InventoryTransact inventoryTransact = this.toStockRequest(acceptRecord);
            int inventoryId = inventoryTransactService.run(inventoryTransact);
            acceptRecord.setInventoryId(inventoryId);
            acceptRecordService.updateById(acceptRecord);

            //Step3. 回写上游单据[入库任务]状态
            //要判断是否需要回写
            if (StringUtils.isNotEmpty(acceptRecord.getAsnDetailNo())) {
                this.updateASNState(acceptRecord);
            }
        }
        return acceptRecords;
    }

    /**
     * 根据收货单生成库存事务
     * @param acceptRecord
     * @return
     */
    private InventoryTransact toStockRequest(AcceptRecord acceptRecord) {
        InventoryTransact inventoryTransact = new InventoryTransact();
        //Step1.准备数据
        //仓库
        inventoryTransact.setWareId(acceptRecord.getWareId());
        inventoryTransact.setWareName(acceptRecord.getWareName());
        //货主
        inventoryTransact.setToOrganizationId(acceptRecord.getOrganizationId());
        inventoryTransact.setToOrganizationName(acceptRecord.getOrganizationName());
        //库位
        inventoryTransact.setToCellCode(acceptRecord.getCellCode());
        //容器
        inventoryTransact.setToBoxCode(acceptRecord.getBoxCode());
        //物料
        inventoryTransact.setItemCode(acceptRecord.getItemCode());
        inventoryTransact.setItemName(acceptRecord.getItemName());
        inventoryTransact.setSpec(acceptRecord.getSpec());
        inventoryTransact.setModel(acceptRecord.getModel());
        inventoryTransact.setImgUrl(acceptRecord.getImgUrl());
        //批次
        inventoryTransact.setToBatchId(acceptRecord.getBatchId());
        inventoryTransact.setToBatchName(acceptRecord.getBatchName());
        //数量
        inventoryTransact.setToQuantity(acceptRecord.getQuantity());
        //包装 转换率
        inventoryTransact.setToPackDetailId(acceptRecord.getPackDetailId());
        inventoryTransact.setToPackDescribe(acceptRecord.getPackDescribe());
        inventoryTransact.setToTransRatio(acceptRecord.getTransRatio());
        //创建人 时间
        inventoryTransact.setCreateUserId(acceptRecord.getAcceptUserId());
        inventoryTransact.setCreateUserName(acceptRecord.getAcceptUserName());
        inventoryTransact.setCreateTime(acceptRecord.getAcceptTime());
        //事务类型
        inventoryTransact.setTransactType(handleTransactType(acceptRecord));
        //来源单据号
        inventoryTransact.setBillNo(acceptRecord.getAsnBillNo());
        //质检标识
        if (ObjectUtil.notEqual(AsnManageConstant.ACCEPT_QC_STATE_EXEMPTION, acceptRecord.getQcState())) {
            //需要质检
            inventoryTransact.setState(InventoryConstant.TRANSACT_STATE_UNNORMAL);
            inventoryTransact.setStateDis("未质检");
        }else {
            inventoryTransact.setState(InventoryConstant.TRANSACT_STATE_NORMAL);
        }

        //Step2.保存，返回
        inventoryTransactService.save(inventoryTransact);
        return inventoryTransact;
    }

    private Integer handleTransactType(AcceptRecord acceptRecord) {
        if (StringUtils.isEmpty(acceptRecord.getAsnBillNo())) {
            //没有来源单据，盲收
            return InventoryConstant.TRANSACT_TYPE_BLIND;
        }
        if (StringUtils.isEmpty(acceptRecord.getBoxCode())) {
            //没有目标容器  到货暂收
            return InventoryConstant.TRANSACT_TYPE_ASN;
        }
        //有目标容器  收货即装箱
        return InventoryConstant.TRANSACT_TYPE_ACCEPT;
    }

//    @Override
//    public String billToErp() {
//
//        try {
//            //请求token
//            MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
//            stringMultiValueMap.add("client_id", "KingdeeK3_Rggytest_EpichustClient");
//            stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
//            stringMultiValueMap.add("grant_type", "client_credentials");
//            String tokenUrl = "https://identityserver:44310/connect/token";
//            String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
//            JSONObject jsonObject = JSONObject.parseObject(clientRg);
//            String token = jsonObject.getString("access_token");
//
//            if(token != null){
//                //调用erp接口获取数据
//                HttpHeaders httpHeaders = new HttpHeaders();
//                httpHeaders.add("Accept", "application/json");
//                httpHeaders.add("Authorization", "Bearer " + token);
//                String url = "http://10.18.3.10:30001/api/dept/getalldepts";
//
//                QueryWrapper<AcceptRecord> qw = Wrappers.query();
//                //季工说字段会做调整，目前取值不定
//                List<AcceptRecord> acceptRecords = acceptRecordMapper.selectList(qw.ne("state", 2));
//                if(acceptRecords.size() > 0){
//                    MultiValueMap<String, String> valueMap = new LinkedMultiValueMap<>();
//                    valueMap.add("data", JSONArray.toJSONString(acceptRecords));
//                    String result = HttpClient.getRequest(url, valueMap, httpHeaders);
//                }
//
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//
//        return null;
//    }

    @Override
    public String billToErp() {

        try {
            //请求token
            MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
            stringMultiValueMap.add("client_id", "KingdeeK3_Rggy_AppClient_Test");
            stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
            stringMultiValueMap.add("grant_type", "client_credentials");
            String tokenUrl = "https://identityserver:44310/connect/token";
            String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
            JSONObject jsonObject = JSONObject.parseObject(clientRg);
            String token = jsonObject.getString("access_token");

            if(token != null){

                QueryWrapper<AcceptRecord> qw = Wrappers.query();
                List<AcceptRecord> acceptRecords = acceptRecordMapper.selectList(qw.eq("is_transmit", "0"));
                for(AcceptRecord ac : acceptRecords){
                    QueryWrapper<AsnMaster> amqw = Wrappers.query();
                    AsnMaster asnMaster = asnMasterMapper.selectOne(amqw.eq("bill_no", ac.getAsnBillNo()));

//                    if(asnMaster != null){
                        OrderToErpBO bo = new OrderToErpBO();
                        QueryWrapper<AsnDetail> adqw = Wrappers.query();
                        List<OrderDetailBO> pd = new ArrayList<>();
                        List<AsnDetail> asnDetails = asnDetailMapper.selectList(adqw.eq("bill_no", ac.getAsnBillNo()));
                        for(AsnDetail asnDetail : asnDetails){
                            OrderDetailBO db = new OrderDetailBO();
                            db.setSourceBillDetailRowIndex(asnDetail.getPackDetailId());
//                            db.setItemId(asnDetail.getExpectPackDetailId());
//                            db.setItemNumber(asnDetail.getItemCode());
//                            db.setItemName(asnDetail.getItemName());
//                            db.setItemModel(asnDetail.getSpec());
//                            db.setAuxPropClassId(asnDetail.getAcceptPackDetailId());
                            db.setAuxPropId(asnDetail.getUpperPackDetailId());
//                            db.setAuxPropName(asnDetail.getAsnUdfDs1());
//                            db.setAuxUnitId(asnDetail.getModifyUserId());
//                            db.setAuxUnitName(asnDetail.getRequestDetailDetailNo());
//                            Boolean batch =  asnDetail.getUda2() == "1" ? true : false;
//                            db.setBatchManager(batch);
                            db.setBatchNo(asnDetail.getModel());
//                            db.setAuxQty(asnDetail.getTransRatio());
//                            db.setAuxCommitQty(asnDetail.getExpectQuantity());
//                            db.setUnitId(asnDetail.getCreateUserId());
                            db.setQty(0.00);
//                            db.setCommitQty(asnDetail.getUpperQuantity());
//                            db.setPlanModeId(Integer.parseInt(asnDetail.getUda3()));
                            db.setMtoNo(asnDetail.getPackCode());
                            db.setRemark(asnDetail.getMemo());
//                            db.setTargetBillTypeId(Integer.parseInt(asnDetail.getPackDescribe()));
//                            Boolean target =  asnDetail.getExpectPackDescribe() == "1" ? true : false;
//                            db.setTargetBillROB(target);
                            db.setProductionDate(asnDetail.getAsnUdfDs2());
                            db.setShelfLifeDays(Integer.parseInt(asnDetail.getAsnUdfDs3()));
//                            db.setSourceBillId(asnMaster.getOrganizationId());
                            db.setStockPlaceId(1);

                            bo.setBillTypeId(Integer.parseInt(asnDetail.getUpperPackDescribe()));
                            pd.add(db);
                        }
//                        bo.setId(asnMaster.getOrganizationId());
//                        bo.setBillTypeId(asnMaster.getBillType());
//                        bo.setBillTypeName(asnMaster.getUda1());
//                        bo.setBillNo(asnMaster.getId().toString());
                        bo.setBillDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyy-MM-dd").parse(asnMaster.getExpectTime())));
                        bo.setSourceBillTypeId(asnMaster.getBillType());
                        bo.setStockId(5924);
//                        bo.setBillStatus(asnMaster.getAsnState());
//                        Boolean bi = asnMaster.getUda2() == "1" ? true : false;
//                        bo.setBillClosed(bi);
//                        bo.setSupplierId(asnMaster.getSupplierId());
//                        bo.setSupplierName(asnMaster.getSupplierName());
//                        bo.setCustomerId(asnMaster.getCreateUserId());
//                        bo.setCustomerName(asnMaster.getCreateUserName());
//                        bo.setDeptId(asnMaster.getModifyUserId());
//                        bo.setDeptName(asnMaster.getUda3());
                        bo.setRemark(asnMaster.getMemo());
                        bo.setDetails(pd);
                        //调用erp接口获取数据
                        CloseableHttpClient client = HttpClients.createDefault();
                        URIBuilder uriBuilder = new URIBuilder("http://10.18.3.10:30001/api/IMBill/PushIMBill");
                        HttpPost post = new HttpPost(uriBuilder.build());
                        StringEntity myEntity = new StringEntity(JSON.toJSONString(bo), "UTF-8");// 构造请求数据
    //                httpHeaders.add("Accept", "application/json");
    //                httpHeaders.add("Authorization", "Bearer " + token);
                        post.setHeader("Content-Type", "application/json");
                        post.addHeader("Authorization", "Bearer " + token);
                        post.setEntity(myEntity);// 设置请求体
                        String responseContent = null; // 响应内容
                        CloseableHttpResponse response = null;
                        try {
                            response = client.execute(post);
                            System.out.println("response===>" + JSON.toJSONString(response));
                            if (response.getStatusLine().getStatusCode() == 200) {
    //                    System.out.println("sucess");
                                //修改推送到智能货柜的数据状态  acceptRecords
                                for(AcceptRecord ar : acceptRecords){
                                    ar.setIsTransmit("1");
                                    acceptRecordMapper.updateById(ar);
                                }
                            }
    //                System.out.println("responseContent:" + responseContent);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }  finally {
                            try {
                                if (response != null)
                                    response.close();

                            } catch (IOException e) {
                                e.printStackTrace();
                            } finally {
                                try {
                                    if (client != null)
                                        client.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
//                }

            }

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        //请求token
        MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
        stringMultiValueMap.add("client_id", "KingdeeK3_Rggytest_EpichustClient");
        stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
        stringMultiValueMap.add("grant_type", "client_credentials");
        String tokenUrl = "https://identityserver:44310/connect/token";
        String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
        JSONObject jsonObject = JSONObject.parseObject(clientRg);
        String token = jsonObject.getString("access_token");
        System.out.println(token);

        if(token != null){
            //调用erp接口获取数据
            CloseableHttpClient client = HttpClients.createDefault();
            URIBuilder uriBuilder = new URIBuilder("http://10.18.3.10:30001/api/IMBill/PushIMBill");
            HttpPost post = new HttpPost(uriBuilder.build());
            OrderToErpBO orderToErpBO = new OrderToErpBO();
//            orderToErpBO.setBillNo("5687");
            orderToErpBO.setBillTypeId(1);
            orderToErpBO.setBillDate("2022-04-02");
            orderToErpBO.setSourceBillTypeId(702);
            orderToErpBO.setStockId(5924);

            List<OrderDetailBO> ods = new ArrayList<>();
            OrderDetailBO od = new OrderDetailBO();
//            od.setSourceBillId(1007157);
            od.setSourceBillDetailRowIndex(1);
            od.setQty(0.00);
            od.setStockPlaceId(1);
            ods.add(od);

            orderToErpBO.setDetails(ods);


//            StringEntity myEntity = new StringEntity(JSON.toJSONString(orderToErpBO), ContentType.APPLICATION_JSON);// 构造请求数据
            StringEntity myEntity = new StringEntity(JSON.toJSONString(orderToErpBO), "UTF-8");// 构造请求数据
//                httpHeaders.add("Accept", "application/json");
//                httpHeaders.add("Authorization", "Bearer " + token);
//            post.addHeader("Accept", "application/json");
            post.setHeader("Content-Type", "application/json");
            post.addHeader("Authorization", "Bearer " + token);
            post.setEntity(myEntity);// 设置请求体
            String responseContent = null; // 响应内容
            CloseableHttpResponse response = null;
            try {
                response = client.execute(post);
//                System.out.println(JSON.toJSONString(response));
                if (response.getStatusLine().getStatusCode() == 200) {

                }
//                System.out.println("responseContent:" + responseContent);
            } catch (Exception e) {
                e.printStackTrace();
            }  finally {
                try {
                    if (response != null)
                        response.close();

                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (client != null)
                            client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Override
    public String billToErpNew(String billNo, String acceptRecordCode) {
        try {
            //请求token
            MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
            stringMultiValueMap.add("client_id", "KingdeeK3_Rggy_AppClient_Test");
            stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
            stringMultiValueMap.add("grant_type", "password");
            stringMultiValueMap.add("username", "epichust");
            stringMultiValueMap.add("password", "hK@vmz0YI1e^thtB");
            String tokenUrl = "https://syecrg.sieyuan.com:44310/connect/token";
            String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
            JSONObject jsonObject = JSONObject.parseObject(clientRg);
            String token = jsonObject.getString("access_token");
            System.out.println(token);

            if(token != null){

                QueryWrapper<AsnMaster> amqw = Wrappers.query();
                AsnMaster asnMaster = asnMasterMapper.selectOne(amqw.eq("bill_no", billNo));

//                    if(asnMaster != null){
                QcOrderToErpBO bo = new QcOrderToErpBO();
                QueryWrapper<QcRecord> qr = Wrappers.query();
                QcRecord qcRecord = qcRecordMapper.selectOne(qr.eq("accept_record_code", acceptRecordCode));
                QueryWrapper<AcceptRecord> ar = Wrappers.query();
                AcceptRecord acceptRecord = acceptRecordMapper.selectOne(ar.eq("accept_record_code", acceptRecordCode));
                QueryWrapper<AsnDetail> adqw = Wrappers.query();
                AsnDetail asnDetail = asnDetailMapper.selectOne(adqw.eq("detail_no", qcRecord.getQcBillNo()));
                bo.setBillTypeId(711);
                bo.setBillNo(acceptRecordCode);
                bo.setBillDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyy-MM-dd").parse(asnMaster.getExpectTime())));
                bo.setSourceBillTypeId(asnMaster.getBillType());
                bo.setRemark(asnMaster.getMemo());
                bo.setSourceBillId(asnMaster.getOrganizationId());
                bo.setSourceBillDetailRowIndex(asnDetail.getCreateUserId());
                bo.setQualifiedQty(qcRecord.getQualifiedQuantity());
                //bo.setQty(asnDetail.getExpectQuantity());qcQuantity
                bo.setQty(acceptRecord.getQuantity());//checkQuantity已检数量
                bo.setSampStdId(1000);
                bo.setInspectionMethodId(353);
                bo.setInspectionResultId(qcRecord.getQcResult() == 0 ? 287 : 286);
                //调用erp接口获取数据
                CloseableHttpClient client = HttpClients.createDefault();
                URIBuilder uriBuilder = new URIBuilder("https://syecrg.sieyuan.com:44398/api/QCBill/PushQCBill");
                HttpPost post = new HttpPost(uriBuilder.build());
                ErpBackRecord erpRecord = new ErpBackRecord();
                erpRecord.setCode(billNo);
                erpRecord.setParam(JSON.toJSONString(bo));

                StringEntity myEntity = new StringEntity(JSON.toJSONString(bo), "UTF-8");// 构造请求数据
                post.setHeader("Content-Type", "application/json");
                post.addHeader("Authorization", "Bearer " + token);
                post.setEntity(myEntity);// 设置请求体
                String responseContent = null; // 响应内容
                CloseableHttpResponse response = null;
                try {
                    response = client.execute(post);
//                    System.out.println("response===>" + JSON.toJSONString(response));
                    HttpEntity entity = response.getEntity();
                    InputStream content = entity.getContent();
                    String msg = inputStream2String(content);
                    if (response.getStatusLine().getStatusCode() == 200) {
                        System.out.println("质检回传erp成功");
                        erpRecord.setCode("200");
                        erpRecord.setState(2);
                        erpRecord.setMsg("质检回传erp成功");
                        erpBackRecordMapper.insert(erpRecord);
                        return msg;
                    }else{
                        System.out.println("质检回传erp报错");
                        erpRecord.setCode(String.valueOf(response.getStatusLine().getStatusCode()));
                        erpRecord.setState(1);
                        erpRecord.setMsg(msg);
                        erpBackRecordMapper.insert(erpRecord);
                        System.out.println(erpRecord.getParam());
                        throw new Exception(msg);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }  finally {
                    try {
                        if (response != null)
                            response.close();

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (client != null)
                                client.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }else {
                throw new Exception("token的值为空");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }

    @Override
    public void updateQcState(String acceptRecordCode,int qcState) {
        acceptRecordMapper.updateQcState(acceptRecordCode,qcState);
    }

    @Override
    public void updateAllQcState(String asnBillNo, int qcState) {
        acceptRecordMapper.updateAllQcState(asnBillNo,qcState);
    }

    @Override
    public List<AcceptRecord> findBillNo(String toBoxCode) {
        return acceptRecordMapper.findBillNo(toBoxCode);
    }

    @Override
    public String checkBillToErp(String billId) {

        try {
            //请求token
            MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
            stringMultiValueMap.add("client_id", "KingdeeK3_Rggy_AppClient_Test");
            stringMultiValueMap.add("client_secret", "TekE%dAISMCvwk7V");
            stringMultiValueMap.add("grant_type", "password");
            stringMultiValueMap.add("username", "epichust");
            stringMultiValueMap.add("password", "hK@vmz0YI1e^thtB");
            String tokenUrl = "https://syecrg.sieyuan.com:44310/connect/token";
            String clientRg = HttpClient.clientRg(tokenUrl, HttpMethod.POST, stringMultiValueMap);
            JSONObject jsonObject = JSONObject.parseObject(clientRg);
            String token = jsonObject.getString("access_token");
            System.out.println(token);
            if(token != null){
                QueryWrapper<AsnMaster> amqw = Wrappers.query();
                HashMap cbMap = new HashMap();
                cbMap.put("billTypeId",711);
                cbMap.put("billId",Integer.parseInt(billId));
                //调用erp接口获取数据
                CloseableHttpClient client = HttpClients.createDefault();
                URIBuilder uriBuilder = new URIBuilder("https://syecrg.sieyuan.com:44398/api/Bill/CheckBill");
                HttpPost post = new HttpPost(uriBuilder.build());
                ErpBackRecord erpRecord = new ErpBackRecord();
                erpRecord.setCode(billId);
                erpRecord.setParam(JSON.toJSONString(cbMap));
                StringEntity myEntity = new StringEntity(JSON.toJSONString(cbMap), "UTF-8");// 构造请求数据
                post.setHeader("Content-Type", "application/json");
                post.addHeader("Authorization", "Bearer " + token);
                post.setEntity(myEntity);// 设置请求体
                String responseContent = null; // 响应内容
                CloseableHttpResponse response = null;
                try {
                    response = client.execute(post);
//                    System.out.println("response===>" + JSON.toJSONString(response));
                    HttpEntity entity = response.getEntity();
                    InputStream content = entity.getContent();
                    String msg = inputStream2String(content);
                    if (response.getStatusLine().getStatusCode() == 200) {
                        System.out.println("审核回传erp成功");
                        erpRecord.setCode("200");
                        erpRecord.setState(2);
                        erpRecord.setMsg("审核回传erp成功");
                        erpBackRecordMapper.insert(erpRecord);
                    }else{
                        System.out.println("审核回传erp报错");
                        erpRecord.setCode(String.valueOf(response.getStatusLine().getStatusCode()));
                        erpRecord.setState(1);
                        erpRecord.setMsg(msg);
                        erpBackRecordMapper.insert(erpRecord);
                        System.out.println(erpRecord.getParam());
                        throw new Exception(msg);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }  finally {
                    try {
                        if (response != null)
                            response.close();

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (client != null)
                                client.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }else {
                throw new Exception("token的取值为空");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }

    public   static   String   inputStream2String(InputStream   is)   throws   IOException{
        ByteArrayOutputStream   baos   =   new ByteArrayOutputStream();
        int   i=-1;
        while((i=is.read())!=-1){
            baos.write(i);
        }
        return   baos.toString();
    }

    /**
     * 容器编码找类型
     *
     * @param code
     * @return
     */
    @Override
    public Map<String,Object> finbyCode(String code) {
        System.out.println("11");
     return    acceptRecordMapper.findByCode(code);
    }

    @Override
    public void StraightHairEmptyWarehouse(AsnMaster asnMaster, CurrentUser currentUser) {
        if(currentUser==null){
            currentUser=new CurrentUser();
            currentUser.setUserId(1);
            currentUser.setUserName("超级管理员");
        }
        //1.封装收货单数据
        List<AcceptRecord> list = new ArrayList<AcceptRecord>();
        // 根据入库任务单号查询明细信息
        List<AsnDetail> details = asnDetailService.findByBillNo(asnMaster.getBillNo());
        for (AsnDetail detail : details) {
            AcceptRecord acceptRecord = new AcceptRecord();
            //收货单号
            acceptRecord.setAcceptRecordCode(codeRuleService.generateCode(SystemManageConstant.CODE_RULE_AC));
            // 仓库、货主和物料信息
            acceptRecord.setWareId(asnMaster.getWareId());
            acceptRecord.setWareName(asnMaster.getWareName());
            acceptRecord.setOrganizationId(asnMaster.getOrganizationId());
            acceptRecord.setOrganizationName(asnMaster.getOrganizationName());
            acceptRecord.setItemCode(detail.getItemCode());
            acceptRecord.setItemName(detail.getItemName());
//            acceptRecord.setSpec(detail.getSpec());
            //包装及转换率
            if(detail.getPackDetailId()==null||detail.getPackDescribe()==null){
                //33469 件
                acceptRecord.setPackDetailId(33469);
                acceptRecord.setPackDescribe("件");
            }else{
                acceptRecord.setPackDetailId(detail.getPackDetailId());
                acceptRecord.setPackDescribe(detail.getPackDescribe());
            }
//            acceptRecord.setTransRatio(detail.getTransRatio());
            //收货数量
            acceptRecord.setExpectQuantity(detail.getExpectQuantity());
            acceptRecord.setQuantity(detail.getExpectQuantity());
            // 无目标容器和库位
            acceptRecord.setBillType(0);
            acceptRecord.setAsnBillNo(asnMaster.getBillNo());
            acceptRecord.setAsnDetailNo(detail.getDetailNo());
            //2.操作人员信息
            Integer userId = currentUser.getUserId();
            String userName = currentUser.getUserName();
            String acceptTime = DateUtils.getNowDateTimeString();
            acceptRecord.setAcceptUserId(userId);
            acceptRecord.setAcceptUserName(userName);
            acceptRecord.setAcceptTime(acceptTime);
            // 批次信息
            Map<String, Object> map = new HashMap<>();
            map.put("detail_no", acceptRecord.getAsnBillNo());
            map.put("in_date", DateUtil.today());
            ItemBatch itemBatch = itemBatchService.getOneByMap(map);
            if (ObjectUtil.isNull(itemBatch)) {
                itemBatch = itemBatchService.createSimpleItemBatch(acceptRecord.getAsnBillNo());
            }
            acceptRecord.setBatchId(itemBatch.getBatchId());
            acceptRecord.setBatchName(itemBatch.getBatchName());
            // 收货单状态-2已确认
            acceptRecord.setState(AsnManageConstant.ACCEPT_STATE_CONFIRMED);
            // 质检状态 0免检
            acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_EXEMPTION);
            // 收货日期
            acceptRecord.setAcceptTime(DateUtil.now());

            // 3.新增收货单
            acceptRecordService.save(acceptRecord);

            //4.修改入库任务明细的状态
            // 设置入库明细的验收数量
            detail.setAcceptQuantity(detail.getExpectQuantity());
            // 物料直接是合格的
            detail.setQcState(1);
            // 状态为全部收货
            detail.setState(3);
            // 修改信息
            asnDetailService.saveOrUpdate(detail);
            list.add(acceptRecord);
        }
        //5.修改入库任务的状态
        //  ASN状态  0-初始化 1-已码盘  2-部分收货  3-全部收货  4-ASN完成  5-超额收货
        asnMaster.setAsnState(3);
        asnMaster.setQcState(1);
        asnMasterService.saveOrUpdate(asnMaster);

        // 创建出库任务 履约号-soUdfHs2
        SoMaster soMaster = new SoMaster();
        /**
         *  新建SO单据
         */

        String tableName = "so_master";
        Integer nextId = validatorService.getNextId(tableName);

        String billNo = "SO" + "-" + nextId;
        Integer createUserId = currentUser.getUserId();
        String createUserName = currentUser.getUserName();
        String createTime = DateUtils.getNowDateTimeString();
        soMaster.setCreateUserId(createUserId);
        soMaster.setCreateUserName(createUserName);
        soMaster.setCreateTime(createTime);
        // 出库单号
        soMaster.setBillNo(billNo);
        // 状态 8-完全发运
        soMaster.setState(8);
        // 仓库信息
        soMaster.setWareId(asnMaster.getWareId());
        soMaster.setWareCode(asnMaster.getWareCode());
        soMaster.setWareName(asnMaster.getWareName());
        // 货主信息
        soMaster.setOrganizationId(asnMaster.getOrganizationId());
        soMaster.setOrganizationName(asnMaster.getOrganizationName());
        soMaster.setOrganizationCode(asnMaster.getOrganizationCode());

        // 时间信息
        soMaster.setOrderTime(DateUtil.now());
        soMaster.setDeliveryTime(DateUtils.getNowDateTimeString());
        soMaster.setExpectTimeFm(DateUtils.getNowDateTimeString());
        soMaster.setExpectTimeTo(DateUtils.getNowDateTimeString());
        soMaster.setBillSource(1);
        //履约号-soUdfHs2
        soMaster.setSoUdfHs2(asnMaster.getUda1());
        // 明细行数
        soMaster.setSoStructure(details.size());
        // 审核状态不需要
        // 客户信息--还是领料部门和领料人--先不填写
        // 保存信息
        soMasterService.save(soMaster);
        // 明细信息
        for (int i = 0; i < details.size(); i++) {
            SoDetail soDetail=new SoDetail();
            AsnDetail detail = details.get(i);
            // 出库任务单号
            soDetail.setBillNo(soMaster.getBillNo());
            String detailNo = soMaster.getBillNo() + "-" + (i + 1);
            // 详情单号
            soDetail.setDetailNo(detailNo);
            // 状态--全部拣货
            soDetail.setState(4);
            // 物料信息
            soDetail.setItemCode(detail.getItemCode());
            soDetail.setItemName(detail.getItemName());
            soDetail.setSpec(detail.getSpec());
            // 数量--订货数，发货数量
            soDetail.setOrderQuantity(detail.getExpectQuantity());
            soDetail.setDeliveryQuantity(detail.getExpectQuantity());
            soDetail.setAllottedQuantity(detail.getExpectQuantity());
            soDetail.setPickQuantity(detail.getExpectQuantity());
            // 设置转换率
            if(detail.getTransRatio()!=null){
                soDetail.setTransRatio(detail.getTransRatio());
            }else{
                soDetail.setTransRatio(1.0);
            }

            // 履约号-soUdfHs2
            soDetail.setSoUdfDs2(detail.getUda1());
            soDetailService.save(soDetail);
        }
        // 回传erp--是否需要
//        soMasterService.outbillToErpNew(billNo);
    }
}

